package com.ruoyi.order.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.dto.order.OrderDto;
import com.ruoyi.common.core.utils.CommonUtil;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.order.config.RabbitMQConfig;
import com.ruoyi.order.domain.ProductOrderItem;
import com.ruoyi.order.enums.*;
import com.ruoyi.order.excepion.BizException;
import com.ruoyi.order.feign.CouponFeignSerivce;
import com.ruoyi.order.feign.DroolsFeignService;
import com.ruoyi.order.feign.domain.Address;
import com.ruoyi.order.domain.JsonData;
import com.ruoyi.order.feign.ProductFeignService;
import com.ruoyi.order.feign.domain.CartItemVO;
import com.ruoyi.order.mapper.ProductOrderItemMapper;
import com.ruoyi.order.mq.OrderMessage;
import com.ruoyi.order.request.ConfirmOrderRequest;
import com.ruoyi.order.request.LockCouponRecordRequest;
import com.ruoyi.order.request.LockProductRequest;
import com.ruoyi.order.request.OrderItemRequest;
import com.ruoyi.order.service.ProductOrderItemService;
import com.ruoyi.order.vo.CouponRecordVO;
import com.ruoyi.order.vo.OrderItemVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.order.mapper.OrderMapper;
import com.ruoyi.order.domain.Order;
import com.ruoyi.order.service.IOrderService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 订单主表Service业务层处理
 *
 * @author 林道敬
 * @date 2025-01-04
 */
@Service
@Slf4j
public class OrderServiceImpl  extends ServiceImpl<OrderMapper, Order> implements IOrderService
{
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private ProductFeignService productFeignService;
    @Autowired
    private CouponFeignSerivce couponFeignSerivce;
    @Autowired
    private ProductOrderItemMapper orderItemMapper;
    @Autowired
    private ProductOrderItemService orderItemService;
    @Autowired
    private DroolsFeignService droolsFeignService;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private RabbitMQConfig rabbitMQConfig;

    @Override
    public R confirmOrder(ConfirmOrderRequest orderRequest) {
        //订单编号
        String orderOutTradeNo = CommonUtil.getStringNumRandom(32);
        //获取收货地址详情
        Address address = this.getUserAddress(orderRequest.getAddressId().get(0));
        //获取用户加入购物车的商品
        List<Long> longList = orderRequest.getProductIdList().stream()
                .map(Long::valueOf)
                .collect(Collectors.toList());
        JsonData jsonData = productFeignService.confirmOrderCartItem(longList);
        System.out.println("jsonData :"+jsonData);
        List<OrderItemVO> orderItemList  = jsonData.getData(new TypeReference< List<OrderItemVO>>(){});
        System.out.println("orderItemList:"+orderItemList);
        BigDecimal totalWeight = orderItemList.stream().map(OrderItemVO::getTotalWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
        log.info("获取的商品:{},总重量{}",orderItemList,totalWeight);
        if(orderItemList == null){
            //购物车商品不存在
            throw new BizException(BizCodeEnum.ORDER_CONFIRM_CART_ITEM_NOT_EXIST);
        }
        //验证价格，减去商品优惠券
        this.checkPrice(orderItemList,orderRequest);
        //锁定优惠券
        this.lockCouponRecords(orderRequest ,orderOutTradeNo );

        //锁定库存
        this.lockProductStocks(orderItemList,orderOutTradeNo);

        //创建订单
        Order order = this.saveProductOrder(orderRequest,orderOutTradeNo,address, totalWeight);

        //创建订单项
        saveProductOrderItems( orderOutTradeNo,  order.getId(), orderItemList);

        //发送延迟消息，用于自动关单
        OrderMessage orderMessage = new OrderMessage();
        orderMessage.setOutTradeNo(orderOutTradeNo);
        rabbitTemplate.convertAndSend(rabbitMQConfig.getEventExchange(),rabbitMQConfig.getOrderCloseDelayRoutingKey(),orderMessage);


        //创建支付
        /*PayInfoVO payInfoVO = new PayInfoVO(orderOutTradeNo,
                productOrderDO.getPayAmount(),orderRequest.getPayType(),
                orderRequest.getClientType(), orderItemList.get(0).getProductTitle(),"",TimeConstant.ORDER_PAY_TIMEOUT_MILLS);

        String payResult = payFactory.pay(payInfoVO);
        if(StringUtils.isNotBlank(payResult)){
            log.info("创建支付订单成功:payInfoVO={},payResult={}",payInfoVO,payResult);
            return JsonData.buildSuccess(payResult);
        }else {
            log.error("创建支付订单失败:payInfoVO={},payResult={}",payInfoVO,payResult);
            return JsonData.buildResult(BizCodeEnum.PAY_ORDER_FAIL);
        }*/
        return R.ok(orderOutTradeNo);
    }

    @Override
    public String queryProductOrderState(String outTradeNo) {
        Order productOrder = orderMapper.selectOne(new QueryWrapper<Order>().eq("out_trade_no",outTradeNo));
        if(productOrder == null){
            return "";
        }else {
            return productOrder.getState();
        }
    }

    @Override
    public boolean closeProductOrder(OrderMessage orderMessage) {
        Order productOrderDO = orderMapper.selectOne(new QueryWrapper<Order>().eq("out_trade_no",orderMessage.getOutTradeNo()));

        if(productOrderDO == null){
            //订单不存在
            log.warn("直接确认消息，订单不存在:{}",orderMessage);
            return true;
        }

        if(productOrderDO.getState().equalsIgnoreCase(ProductOrderStateEnum.PAY.name())){
            //已经支付
            log.info("直接确认消息,订单已经支付:{}",orderMessage);
            return true;
        }
        orderMapper.updateOrderPayState(productOrderDO.getOutTradeNo(),ProductOrderStateEnum.CANCEL.name(),ProductOrderStateEnum.NEW.name());
        return true;
    }

    /**
     * 获取收货地址详情
     * @param addressId
     * @return
     */
    private Address getUserAddress(String addressId) {
        Address address = productFeignService.getAddressById(addressId);
        return address;
    }
    /**
     * 获取优惠券
     * @param couponRecordId
     * @return
     */
    private CouponRecordVO getCartCouponRecord(Long couponRecordId) {

        if(couponRecordId ==null || couponRecordId < 0){
            return null;
        }

        JsonData couponData = couponFeignSerivce.findUserCouponRecordById(couponRecordId);

        if(couponData.getCode()!=0){
            throw new BizException(BizCodeEnum.ORDER_CONFIRM_COUPON_FAIL);
        }

        if(couponData.getCode()==0){

            CouponRecordVO couponRecordVO = couponData.getData(new TypeReference<CouponRecordVO>(){});

            if(!couponAvailable(couponRecordVO)){
                log.error("优惠券使用失败");
                throw new BizException(BizCodeEnum.COUPON_UNAVAILABLE);
            }
            return couponRecordVO;
        }

        return null;
    }

    /**
     * 判断优惠券是否可用
     * @param couponRecordVO
     * @return
     */
    private boolean couponAvailable(CouponRecordVO couponRecordVO) {

        if(couponRecordVO.getUseState().equalsIgnoreCase(CouponStateEnum.NEW.name())){
            long currentTimestamp = CommonUtil.getCurrentTimestamp();
            long end = couponRecordVO.getEndTime().getTime();
            long start = couponRecordVO.getStartTime().getTime();
            if(currentTimestamp>= start && currentTimestamp<=end){
                return true;
            }
        }
        return false;
    }
    /**
     * 验证价格
     * 1）统计全部商品的价格
     * 2) 获取优惠券(判断是否满足优惠券的条件)，总价再减去优惠券的价格 就是 最终的价格
     *
     * @param orderItemList
     * @param orderRequest
     */
    private void checkPrice(List<OrderItemVO> orderItemList, ConfirmOrderRequest orderRequest) {

        //统计商品总价格
        BigDecimal realPayAmount = new BigDecimal("0");
        if (orderItemList != null) {
            for(OrderItemVO orderItemVO : orderItemList){
                BigDecimal itemRealPayAmount = orderItemVO.getTotalAmount();
                realPayAmount = realPayAmount.add(itemRealPayAmount);
            }
        }

        //获取优惠券，判断是否可以使用
        CouponRecordVO couponRecordVO = getCartCouponRecord(Long.valueOf(orderRequest.getCouponRecordIds().get(0)));

        //计算购物车价格，是否满足优惠券满减条件
        if(couponRecordVO!=null){

            //计算是否满足满减
            if(realPayAmount.compareTo(couponRecordVO.getConditionPrice()) < 0){
                throw new BizException(BizCodeEnum.ORDER_CONFIRM_COUPON_FAIL);
            }
            if(couponRecordVO.getPrice().compareTo(realPayAmount)>0){
                realPayAmount = BigDecimal.ZERO;

            }else {
                realPayAmount = realPayAmount.subtract(couponRecordVO.getPrice());
            }

        }

        if(realPayAmount.compareTo(orderRequest.getRealPayAmount()) !=0 ){
            log.error("订单验价失败：{}",orderRequest);
            throw new BizException(BizCodeEnum.ORDER_CONFIRM_PRICE_FAIL);
        }
    }
    /**
     * 锁定优惠券
     * @param orderRequest
     * @param orderOutTradeNo
     */
    private void lockCouponRecords(ConfirmOrderRequest orderRequest, String orderOutTradeNo) {
        List<Long> lockCouponRecordIds = new ArrayList<>();
        if(Long.valueOf(orderRequest.getCouponRecordIds().get(0))>0){
            lockCouponRecordIds.add(Long.valueOf(orderRequest.getCouponRecordIds().get(0)));

            LockCouponRecordRequest lockCouponRecordRequest = new LockCouponRecordRequest();
            lockCouponRecordRequest.setOrderOutTradeNo(orderOutTradeNo);
            lockCouponRecordRequest.setLockCouponRecordIds(lockCouponRecordIds);

            //发起锁定优惠券请求
            JsonData jsonData = couponFeignSerivce.lockCouponRecords(lockCouponRecordRequest);
            if(jsonData.getCode()!=0){
                throw new BizException(BizCodeEnum.COUPON_RECORD_LOCK_FAIL);
            }
        }
    }
    /**
     * 锁定商品库存
     * @param orderItemList
     * @param orderOutTradeNo
     */
    private void lockProductStocks(List<OrderItemVO> orderItemList, String orderOutTradeNo) {

        List<OrderItemRequest> itemRequestList = orderItemList.stream().map(obj->{

            OrderItemRequest request = new OrderItemRequest();
            request.setBuyNum(obj.getBuyNum());
            request.setProductId(obj.getProductId());
            return request;
        }).collect(Collectors.toList());


        LockProductRequest lockProductRequest = new LockProductRequest();
        lockProductRequest.setOrderOutTradeNo(orderOutTradeNo);
        lockProductRequest.setOrderItemList(itemRequestList);

        JsonData jsonData = productFeignService.lockProductStock(lockProductRequest);
        if(jsonData.getCode()!=0){
            log.error("锁定商品库存失败：{}",lockProductRequest);
            throw new BizException(BizCodeEnum.ORDER_CONFIRM_LOCK_PRODUCT_FAIL);
        }
    }

    /**
     * 创建订单
     * @param orderRequest
     * @param orderOutTradeNo
     */
    private Order saveProductOrder(ConfirmOrderRequest orderRequest, String orderOutTradeNo, Address address,BigDecimal totalWeight) {

        OrderDto orderDto = new OrderDto();
        orderDto.setDistance(address.getDistance().doubleValue());
        orderDto.setWeight(totalWeight.doubleValue());
        String droolsResult = droolsFeignService.orderDrools(orderDto);
        BigDecimal fee =new BigDecimal(droolsResult);


        Order productOrderDO = new Order();
        productOrderDO.setTotalWeight(totalWeight);
        productOrderDO.setPayFee(fee);

        productOrderDO.setUserId(1l);
        productOrderDO.setNickname("lindaojing");

        productOrderDO.setOutTradeNo(orderOutTradeNo);
        productOrderDO.setCreateTime(new Date());
        productOrderDO.setDel(0l);
        productOrderDO.setOrderType(ProductOrderTypeEnum.DAILY.name());

        //实际支付的价格
        productOrderDO.setPayAmount(orderRequest.getRealPayAmount().add(fee));

        //总价，未使用优惠券的价格
        productOrderDO.setTotalAmount(orderRequest.getTotalAmount());
        productOrderDO.setState(ProductOrderStateEnum.NEW.name());
       // productOrderDO.setPayType(ProductOrderPayTypeEnum.valueOf(orderRequest.getPayType()).name());

        productOrderDO.setReceiverAddress(JSON.toJSONString(address));

        orderMapper.insert(productOrderDO);
        return productOrderDO;

    }


    /**
     * 新增订单项
     * @param orderOutTradeNo
     * @param
     * @param orderItemList
     */
    private void saveProductOrderItems(String orderOutTradeNo, Long orderId, List<OrderItemVO> orderItemList) {


        List<ProductOrderItem> list = orderItemList.stream().map(
                obj->{
                    ProductOrderItem itemDO = new ProductOrderItem();
                    itemDO.setBuyNum(obj.getBuyNum());
                    itemDO.setProductId(obj.getProductId());
                    itemDO.setProductImg(obj.getProductImg());
                    itemDO.setProductName(obj.getProductTitle());
                    itemDO.setWeight(obj.getWeight());
                    itemDO.setTotalWeight(obj.getTotalWeight());
                    itemDO.setOutTradeNo(orderOutTradeNo);
                    itemDO.setCreateTime(new Date());

                    //单价
                    itemDO.setAmount(obj.getAmount());
                    //总价
                    itemDO.setTotalAmount(obj.getTotalAmount());
                    itemDO.setProductOrderId(orderId);
                    return itemDO;
                }
        ).collect(Collectors.toList());
        orderItemService.saveBatch(list);
    }

    /**
     * 查询订单主表
     *
     * @param id 订单主表主键
     * @return 订单主表
     */
    @Override
    public Order selectOrderById(Long id)
    {
        return orderMapper.selectOrderById(id);
    }

    /**
     * 查询订单主表列表
     *
     * @param order 订单主表
     * @return 订单主表
     */
    @Override
    public List<Order> selectOrderList(Order order)
    {
        return orderMapper.selectOrderList(order);
    }

    /**
     * 新增订单主表
     *
     * @param order 订单主表
     * @return 结果
     */
    @Transactional
    @Override
    public int insertOrder(Order order)
    {
        order.setCreateTime(DateUtils.getNowDate());
        int rows = orderMapper.insertOrder(order);
        insertProductOrderItem(order);
        return rows;
    }

    /**
     * 修改订单主表
     *
     * @param order 订单主表
     * @return 结果
     */
    @Transactional
    @Override
    public int updateOrder(Order order)
    {
        order.setUpdateTime(DateUtils.getNowDate());
        orderMapper.deleteProductOrderItemByProductOrderId(order.getId());
        insertProductOrderItem(order);
        return orderMapper.updateOrder(order);
    }

    /**
     * 批量删除订单主表
     *
     * @param ids 需要删除的订单主表主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteOrderByIds(Long[] ids)
    {
        orderMapper.deleteProductOrderItemByProductOrderIds(ids);
        return orderMapper.deleteOrderByIds(ids);
    }

    /**
     * 删除订单主表信息
     *
     * @param id 订单主表主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteOrderById(Long id)
    {
        orderMapper.deleteProductOrderItemByProductOrderId(id);
        return orderMapper.deleteOrderById(id);
    }

    /**
     * 新增订单子表信息
     *
     * @param order 订单主表对象
     */
    public void insertProductOrderItem(Order order)
    {
        List<ProductOrderItem> productOrderItemList = order.getProductOrderItemList();
        Long id = order.getId();
        if (StringUtils.isNotNull(productOrderItemList))
        {
            List<ProductOrderItem> list = new ArrayList<ProductOrderItem>();
            for (ProductOrderItem productOrderItem : productOrderItemList)
            {
                productOrderItem.setProductOrderId(id);
                list.add(productOrderItem);
            }
            if (list.size() > 0)
            {
                orderMapper.batchProductOrderItem(list);
            }
        }
    }
}
